# coding=utf-8
import os
import sys
import json
import hashlib
import configparser

# Error Codes
ERROR_SUCCESS = 0
ERROR_CONVERT = 88  # addon转换失败
ERROR_JSON_READ = 89  # 转换时老addon json文件读取失败
ERROR_CHECK = 90  # 转换时addon版本校验出错


def gen_md5(input_string):
    """Generate md5 based on command block contents

    Args:
        input_string (String): Command Block Object String

    Returns:
        String: md5
    """
    md5_hash = hashlib.md5()
    md5_hash.update(input_string.encode("utf-8"))
    hash_result = md5_hash.hexdigest()

    return hash_result


def convert_data_to_block_app(data, blockName):
    """_summary_

    Args:
        data (array): List object containing command block information

    Returns:
        object: block(initJson) xml message
    """
    try:
        arg_num = 0
        args = "args0"
        messages = ["message0"]

        block = {
            "type": "custom_block_",
            "message0": None,
            "args0": [],
            "colour": "#FFBF00",
        }

        for i, item in enumerate(data):
            arg_type = item["type"]
            arg_name = item["name"]
            argText = item["name"] + "@" + blockName
            arg_value = item["value"]
            arg_disable = 1 if item.get("disabled", False) else 0

            if arg_type == "text":
                block[args].append(
                    {
                        "type": "field_label",
                        "name": arg_name,
                        "text": argText,
                        "disabled": arg_disable,
                    }
                )
            elif arg_type == "field_dropdown":
                if arg_disable:
                    block[args].append(
                        {
                            "type": "input_value",
                            "name": arg_name,
                            "text": argText,
                            "disabled": 1,
                        }
                    )
                else:
                    options = [[item[0], str(item[1])] for item in arg_value]
                    block[args].append(
                        {
                            "type": "field_dropdown",
                            "name": arg_name,
                            "options": options,
                        }
                    )
            elif arg_type == "statement":
                if arg_num == 0:
                    arg_num += 1
                    args = "args" + str(arg_num)
                    messages.append("message" + str(arg_num))
                    block[args] = []

                    block[args].append(
                        {
                            "type": "field_label",
                            "name": "placeholder",
                            "text": argText,
                        }
                    )
                else:
                    block[args].append(
                        {
                            "type": "field_label",
                            "name": "placeholder",
                            "text": argText,
                        }
                    )
                arg_num += 1
                args = "args" + str(arg_num)
                messages.append("message" + str(arg_num))
                block[args] = []

                block[args].append(
                    {
                        "type": "input_statement",
                        "name": arg_name,
                    }
                )

            elif arg_type == "obj_text":
                block[args].append(
                    {
                        "type": "input_value",
                        "name": arg_name,
                        "text": arg_value,
                        "check": "String",
                        "disabled": arg_disable,
                    }
                )

        for i, msg in enumerate(messages):
            block[msg] = generate_message_to_block(block["args" + str(i)], i)

        block["previousStatement"] = None
        block["nextStatement"] = None
        block["type"] = block["type"] + gen_md5(str(block))
        xml = convert_block_to_xml(block)
        msg = convert_message_to_app(data, blockName)

        re = {"block": block, "xml": xml, "msg": msg}
        # print(re)
        return re

    except Exception as e:

        print("Command conversion failure:", str(e))
        return ERROR_CONVERT  # Return error code


def generate_message_to_block(arg, index):
    placeholders = ["%" + str(i + 1) for i in range(len(arg))]
    return " ".join(placeholders)


def convert_block_to_xml(block):
    try:
        xml = '<block type="' + block["type"] + '" >'
        arg_num = 0
        args = "args" + str(arg_num)

        while args in block:
            for i, arg in enumerate(block[args]):
                try:
                    if arg["disabled"]:
                        isDisabled = ' disabled = "true" '
                    else:
                        isDisabled = ' disabled = "false" '
                except:
                    pass

                if "name" in arg:
                    arg["name"] = arg["name"].replace("&", "&amp;").replace("<", "&lt;")
                if "text" in arg:
                    arg["text"] = arg["text"].replace("&", "&amp;").replace("<", "&lt;")
                if arg["type"] == "field_label":
                    xml += '<field name="' + arg["name"] + '"' + isDisabled + ">#" + arg["text"] + "</field>"
                elif arg["type"] == "input_value":
                    xml += '<value name="' + arg["name"] + '"' + isDisabled + ">"
                    xml += '<shadow type="text"' + isDisabled + ">"
                    xml += '<field name="TEXT">' + arg["text"] + "</field>"
                    xml += "</shadow>"
                    xml += "</value>"
                elif arg["type"] == "field_dropdown":
                    xml += '<field name="' + arg["name"] + '">' + str(arg["options"][0][1]) + "</field>"
                elif arg["type"] == "input_statement":
                    xml += '<statement name="' + arg["name"] + '"></statement>'
            arg_num += 1
            args = "args" + str(arg_num)
        xml += "</block>"
        return xml
    except Exception as e:
        print("xml 转换失败", e)
        return ""  # Return empty string on error


def convert_message_to_app(data, blockName):
    try:
        msg = {"en": {}, "zh": {}, "ja": {}}

        for item in data:
            if item["type"] == "text" or item["type"] == "statement":
                msg["en"][item["name"] + "@" + blockName] = item["value"].get("en", item["value"].get("zh", item["value"].get("ja", " ")))
                msg["zh"][item["name"] + "@" + blockName] = item["value"].get("zh", item["value"].get("en", " "))
                msg["ja"][item["name"] + "@" + blockName] = item["value"].get("ja", item["value"].get("en", " "))
            elif item["type"] == "field_dropdown":
                for option in item["value"]:
                    msg["en"][option[0]] = option[0]
                    msg["zh"][option[0]] = option[0]
                    msg["ja"][option[0]] = option[0]

        return msg
    except Exception as e:
        return {}  # Return empty dictionary on error


def convert_new_json(inputJson):
    try:
        inputJson_message = inputJson["blockInfos"][0]["message"]

        newJson = {
            "JAKA_BLOCK_DATA": [],
            "blockName": inputJson["blockname"],
            "jksUrl": inputJson["blockInfos"][0]["jskurl"],
            "openUrl": inputJson["blockInfos"][0]["openurl"],
        }
        blockNamaObj = {"index": 0, "name": "blockname_", "type": "text", "source": "None", "disabled": False, "value": {"zh": "", "en": "", "ja": ""}}

        for lan in ["zh", "en", "ja"]:
            objCountInner = 0

            for msg in inputJson_message[lan].split(" "):
                if "%" in msg:
                    objCountInner += 1
                    continue
                if objCountInner == 0:
                    if lan == "en":
                        blockNamaObj["name"] += msg

                    blockNamaObj["value"][lan] += msg + " "

        newJson["JAKA_BLOCK_DATA"].append(blockNamaObj)

        for index_i, block in enumerate(inputJson["blockInfos"]):
            if index_i == 0:
                objCount = 0
                type_flag = ""

                for index_j, argument in enumerate(block["arguments"]):
                    tempDic = {}
                    tempDic["index"] = index_j
                    tempDic["name"] = argument["key"]
                    tempDic["type"] = argument["type"]
                    tempDic["source"] = "None"
                    tempDic["pageShow"] = False
                    tempDic["alias"] = {"zh": "", "en": "", "ja": ""}
                    tempDic["disabled"] = argument.get("disabled", False)
                    tempDic["_X_ROW_KEY"] = "row_1" + str(index_j)
                    if tempDic["type"] == "text":
                        if type_flag != "text":
                            tempDic["value"] = {"zh": "", "en": "", "ja": ""}
                            for lan in ["zh", "en", "ja"]:
                                objCountInner = 0
                                for msg in block["message"][lan].split(" "):
                                    # print(objCountInner,msg,objCount)
                                    if "%" in msg:
                                        objCountInner += 1
                                        continue
                                    if objCountInner == objCount:
                                        tempDic["value"][lan] += msg + " "
                            newJson["JAKA_BLOCK_DATA"].append(tempDic)
                        else:
                            pass

                    else:
                        tempDic["value"] = argument["value"]
                        objCount += 1
                        newJson["JAKA_BLOCK_DATA"].append(tempDic)

                    type_flag = argument["type"]

            else:
                newJson["jksUrl" + str(index_i)] = block["jskurl"]
                tempDic = {}
                tempDic["index"] = "JAKA_CUSTOM_SUBSTACK" + str(index_i - 1)
                tempDic["name"] = "JAKA_CUSTOM_SUBSTACK" + str(index_i - 1)
                tempDic["type"] = "statement"
                tempDic["source"] = "None"
                tempDic["pageShow"] = False
                tempDic["alias"] = {"zh": "", "en": "", "ja": ""}
                tempDic["disabled"] = False
                tempDic["_X_ROW_KEY"] = "row_s" + str(index_i)
                tempDic["value"] = {"zh": "", "en": "", "ja": ""}
                for lan in ["zh", "en", "ja"]:
                    tempDic["value"][lan] = block["message"][lan]
                newJson["JAKA_BLOCK_DATA"].append(tempDic)

        return newJson
    except Exception as e:
        return {}  # Return empty dictionary on error


def AddOn_OldToNew(AddOnName):
    try:
        OldToNew_CustomPrograms = []
        folder_path = jkzuc.jkroot_dir + "/configs/JAKA/AddOns/"
        custom_programs_path = os.path.join(folder_path, AddOnName, "customprograms")

        for filename in os.listdir(custom_programs_path):
            if filename.endswith(".json"):
                json_file_path = os.path.join(custom_programs_path, filename)

                try:
                    with open(json_file_path, "r") as json_file:
                        data = json.load(json_file)
                except Exception as e:
                    return ERROR_JSON_READ

                new_data = convert_new_json(data)
                re = convert_data_to_block_app(new_data["JAKA_BLOCK_DATA"], new_data["blockName"])

                new_data["BLOCK_TYPE"] = re["block"]["type"]
                new_data["JAKA_BLOCK_DATA"] = json.dumps({"initJson": re["block"], "xml": re["xml"], "message": re["msg"]})

                OldToNew_CustomPrograms.append(new_data)

        output_file_path = os.path.join(folder_path, AddOnName, "OldToNew_CustomPrograms.json")
        with open(output_file_path, "w") as output_file:
            json.dump(OldToNew_CustomPrograms, output_file, indent=4)

        return ERROR_SUCCESS
    except Exception as e:
        return ERROR_CONVERT  # Return error code


def AddOn_check(folder_path, folder_name):
    """Iterate through the folder to check if it's an older version, if it is and has a command block then convert it

    Args:
        folder_path (str): AddOns folder
        folder_name (str): AddOn folder(name)
    """
    try:
        config_file_path = os.path.join(folder_path, folder_name + "_config.ini")

        if os.path.exists(config_file_path):
            config = configparser.ConfigParser()
            config.read(config_file_path)

            if config.has_section("AddOnInfo") and config.has_option("AddOnInfo", "convention"):
                convention_value = config.get("AddOnInfo", "convention")

                if convention_value.split(".")[0] == "2":
                    return AddOn_OldToNew(folder_name)

        return ERROR_SUCCESS
    except Exception as e:
        return ERROR_CHECK


if __name__ == "__main__":
    try:
        exit_error = 0
        folder_path = jkzuc.jkroot_dir + "/configs/JAKA/AddOns/"

        for folder_name in os.listdir(folder_path):
            folder_path_full = os.path.join(folder_path, folder_name)

            if os.path.isdir(folder_path_full):
                error_code = AddOn_check(folder_path_full, folder_name)
                if error_code == ERROR_SUCCESS:
                    print("Operation completed for folder:", folder_name)
                else:
                    exit_error = error_code
                    print("Error occurred for folder:", folder_name, "Error Code:", error_code)

        sys.exit(exit_error)
    except Exception as e:
        print("An unexpected error occurred:", str(e))
        sys.exit(ERROR_CONVERT)
